home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 9825 / 9825.xpi / chrome / content / popup_bubble.js < prev    next >
Text File  |  2010-01-12  |  46KB  |  943 lines

  1. //Note to editor: NOT executed from XUL
  2. //Copyright 2009 Yongqian Li.
  3.  
  4. (function()
  5. {
  6.     var yandex_lang_codes = ['ru', 'rus',
  7.         'uk', 'ukr',
  8.         'be', 'bel',
  9.         'kk', 'kaz',
  10.         'uz', 'uzb',
  11.         'kaa', 'kaa',
  12.         'tk', 'tuk',
  13.         'tut', 'gag',
  14.         'mo', 'mol',
  15.         'ky', 'kir',
  16.         'et', 'est',
  17.         'lt', 'lit',
  18.         'lv', 'lav',
  19.         'hy', 'arm', 'hye', 
  20.         'az', 'aze',
  21.         'ka', 'geo', 'kat',
  22.         'tg', 'tgk'];
  23.  
  24.     var show_yandex = false;
  25.     for(var x = 0; x < yandex_lang_codes.length; x++)
  26.     {
  27.         if(navigator.language == yandex_lang_codes[x] || navigator.language.indexOf(yandex_lang_codes[x] + "-") == 0)
  28.         {
  29.             show_yandex = true;
  30.         }
  31.     }
  32.  
  33.  
  34.     /* //BEGIN FasterFox widget specific code
  35.     var $ = window.finderfox_$
  36.     var config = {
  37.         showPopupBubble: true,
  38.         openNewTab: true,
  39.         forceSingleRow: false,
  40.         animate: true,
  41.         enableGhosting: false,
  42.         source: "finderfox",
  43.  
  44.         customSearchEngines: [],
  45.  
  46.         searchWikipedia: true,
  47.         searchOneRiot: true,
  48.         searchYandex: false,        
  49.         searchDelicious: false,
  50.         searchTwitter: false,
  51.         searchSurfCanyon: true,
  52.         tweetThis: true,
  53.         searchBing: false,
  54.         searchBaidu: false,
  55.         searchReddit: false,
  56.         searchYouTube: false,
  57.         searchWiktionary: false,
  58.         searchGoogle: true,        
  59.         showHomepageLink: true
  60.     };    
  61.     if(!$.support.opacity)
  62.     {
  63.         config.animate = false;
  64.     }
  65.     
  66.     if(show_yandex && config.searchGoogle && !config.searchYandex)
  67.     {
  68.         //default config, override
  69.         config.searchGoogle = false;
  70.         config.searchYandex = true;
  71.     }
  72.  
  73.     var ext_config = window.finderfoxConfig;
  74.     if(ext_config)
  75.     {
  76.         if(ext_config.customSearchEngines && 
  77.            ext_config.customSearchEngines.length > 0)
  78.         {
  79.             config.customSearchEngines = [ext_config.customSearchEngines[0]];
  80.             config.searchTwitter = false;
  81.         }        
  82.     }
  83.     window.finderfox = {
  84.         //config: config,
  85.         disable: function()
  86.         {
  87.             config.showPopupBubble = false;
  88.         }
  89.     };
  90.     */ //END FasterFox widget specific code
  91.     
  92.     //BEGIN SmarterFox specific code
  93.     //var $ = smarterwiki_$;
  94.     var safe_SW_getBoolPref = function(name)
  95.     {
  96.         try
  97.         {
  98.             return SW_getBoolPref(name);
  99.         }
  100.         catch(err)
  101.         {
  102.             return null;
  103.         }
  104.     };
  105.     
  106.     var config = {
  107.         get showPopupBubble() 
  108.         {
  109.             if(unsafeWindow.finderfox)
  110.             {
  111.                 /*
  112.                 if(safe_SW_getBoolPref("extensions.smarterwiki.show_popup_bubble")) //I override the embedded
  113.                 {
  114.                     unsafeWindow.finderfox.disable(); 
  115.                     return true;
  116.                 }
  117.                 */
  118.                 return false; //the embedded widget overrides me
  119.             }
  120.             return safe_SW_getBoolPref("extensions.smarterwiki.show_popup_bubble");
  121.         },
  122.         get openNewTab() 
  123.         {
  124.             return safe_SW_getBoolPref("extensions.smarterwiki.popup_bubble_open_new_tab");
  125.         },
  126.         get forceSingleRow()
  127.         {
  128.             return safe_SW_getBoolPref("extensions.smarterwiki.popup_bubble_force_single_row");
  129.         },
  130.         animate: true,
  131.         enableGhosting: true,
  132.         source: "smarterfox",
  133.         get customSearchEngines()
  134.         {
  135.             return [
  136.             /*
  137.                 [
  138.                     "Diig search", 
  139.                     "http://www.digg.com/favicon.ico", 
  140.                     "http://diig.com{searchTerms}"
  141.                 ],
  142.                 [
  143.                     "Diig search", 
  144.                     "http://www.digg.com/favicon.ico", 
  145.                     "http://diig.com{searchTerms}"
  146.                 ],
  147.             */
  148.             ];
  149.             //return [];
  150.         },
  151.  
  152.         get searchWikipedia()
  153.         {
  154.             return true;
  155.         },
  156.         get searchOneRiot()
  157.         {
  158.             return safe_SW_getBoolPref("extensions.smarterwiki.search_oneriot");
  159.         },
  160.         get searchYandex()
  161.         {
  162.             return safe_SW_getBoolPref("extensions.smarterwiki.search_yandex");
  163.             /*
  164.             var pref_searchYandex = safe_SW_getBoolPref("extensions.smarterwiki.search_yandex");
  165.             var pref_searchGoogle = safe_SW_getBoolPref("extensions.smarterwiki.search_google");
  166.             if(show_yandex && pref_searchGoogle && !pref_searchYandex)
  167.             {
  168.                 //default config, override
  169.                 return true;
  170.             }
  171.             return pref_searchYandex;
  172.             */
  173.         },
  174.         get searchDelicious()
  175.         {
  176.             return safe_SW_getBoolPref("extensions.smarterwiki.search_delicious");
  177.         },
  178.         get searchTwitter()
  179.         {
  180.             return safe_SW_getBoolPref("extensions.smarterwiki.search_twitter");
  181.         },
  182.         get searchSurfCanyon()
  183.         {
  184.             return safe_SW_getBoolPref("extensions.smarterwiki.search_surfcanyon");
  185.         },
  186.         get tweetThis()
  187.         {
  188.             return safe_SW_getBoolPref("extensions.smarterwiki.tweet_this");
  189.         },
  190.         get searchBing()
  191.         {
  192.             return safe_SW_getBoolPref("extensions.smarterwiki.search_bing");
  193.         },
  194.         get searchBaidu()
  195.         {
  196.             return safe_SW_getBoolPref("extensions.smarterwiki.search_baidu");
  197.         },
  198.         get searchReddit()
  199.         {
  200.             return safe_SW_getBoolPref("extensions.smarterwiki.search_reddit");
  201.         },
  202.         get searchYouTube()
  203.         {
  204.             return safe_SW_getBoolPref("extensions.smarterwiki.search_youtube");
  205.         },
  206.         get searchWiktionary()
  207.         {
  208.             return safe_SW_getBoolPref("extensions.smarterwiki.search_wiktionary");
  209.         },
  210.         get searchGoogle()
  211.         {
  212.             return safe_SW_getBoolPref("extensions.smarterwiki.search_google");
  213.             /*
  214.             var pref_searchYandex = safe_SW_getBoolPref("extensions.smarterwiki.search_yandex");
  215.             var pref_searchGoogle = safe_SW_getBoolPref("extensions.smarterwiki.search_google");
  216.             if(show_yandex && pref_searchGoogle && !pref_searchYandex)
  217.             {
  218.                 //default config, override
  219.                 return false;
  220.             }
  221.             return pref_searchGoogle;
  222.             */
  223.         },
  224.         showHomepageLink: false,
  225.     };    
  226.     //END SmarterFox specific code
  227.  
  228.  
  229.     var get_config = function(callback)
  230.     {
  231.         callback(config);
  232.     };
  233.     if(window.chrome && window.chrome.extension) // detect chrome
  234.     {
  235.         $.prototype.ready = function(callback) {
  236.             callback();
  237.         };//doesn't work on Chrome, cheap hack
  238.         
  239.         get_config = function(callback)
  240.         {
  241.             var config = {
  242.                 animate: true,
  243.                 enableGhosting: true,
  244.                 source: "smarterfox",
  245.                 customSearchEngines: [],
  246.                 searchWikipedia: true,
  247.                 showHomepageLink: false
  248.             };
  249.             var config_map = {
  250.                 showPopupBubble: "show_popup_bubble",
  251.                 openNewTab: "popup_bubble_open_new_tab",
  252.                 forceSingleRow: "popup_bubble_force_single_row",
  253.                 searchOneRiot: "search_oneriot",
  254.                 searchYandex: "search_yandex",
  255.                 searchDelicious: "search_delicious",
  256.                 searchTwitter: "search_twitter",
  257.                 searchSurfCanyon: "search_surfcanyon",
  258.                 tweetThis: "tweet_this",
  259.                 searchBing: "search_bing",
  260.                 searchBaidu: "search_baidu",
  261.                 searchReddit: "search_reddit",
  262.                 searchYouTube: "search_youtube",
  263.                 searchWiktionary: "search_wiktionary",
  264.                 searchGoogle: "search_google"
  265.             };
  266.             
  267.             var get_localStorage = function(key, callback) //only used for Chrome
  268.             {    
  269.                 chrome.extension.sendRequest({"msg_type": "get_localStorage", "key": key}, function(response)
  270.                 {
  271.                     if(callback)
  272.                     {
  273.                         callback(response.value);
  274.                     }
  275.                 });
  276.             };
  277.             getBoolPref = function(pref_name, callback)
  278.             {
  279.                 get_localStorage("pref." + pref_name, function(str)
  280.                 {
  281.                     callback(str == "true");
  282.                 });
  283.             };
  284.  
  285.             for(var key in config_map)
  286.             {
  287.                 (function(prop_name)
  288.                 {
  289.                     getBoolPref(config_map[prop_name], function(pref_value)
  290.                     {
  291.                         config[prop_name] = pref_value;
  292.                         config_map[prop_name] = null;
  293.                         for(var prop_name2 in config_map) {
  294.                             if(config_map[prop_name2]) {
  295.                                 return;
  296.                             }
  297.                         }
  298.                         /*
  299.                         if(window.finderfox) {
  300.                             config["showPopupBubble"] = false;
  301.                         }*///doesn't work :(
  302.                         callback(config);
  303.                     });
  304.                 })(key);
  305.             }
  306.         };
  307.     }
  308.     
  309.  
  310.  
  311.  
  312.     var get_log_msg_url = function(msg)
  313.     {
  314.         msg["rand"] = parseInt(Math.random() * 1000000000);
  315.         var params = [];
  316.         for(var k in msg)
  317.         {
  318.             params.push(encodeURIComponent(k) + "=" + encodeURIComponent(msg[k]));
  319.         }
  320.         /*
  321.         if("https:" == document.location.protocol)
  322.         {
  323.             return "https://ssl.msgs.smarterfox.com/log_msg?" + params.join("&");
  324.         }
  325.         */
  326.         return "http://msgs.smarterfox.com/log_msg?" + params.join("&");
  327.     };
  328.     
  329.  
  330.     var log_msg_async = function(msg, callback)
  331.     {
  332.         var $ting = $('<img style="display: none;" />');
  333.         if(callback)
  334.         {
  335.             $ting.load(callback);
  336.         }
  337.         $ting.attr("src", get_log_msg_url(msg));
  338.         return $ting;
  339.     };
  340.  
  341.     
  342.     /*//doesn't work for some reason :(
  343.     var log_msg_async = function(msg, callback)
  344.     {
  345.         var ting = new Image(1, 1);
  346.         if(callback)
  347.         {
  348.             ting.onload = callback;
  349.         }
  350.         ting.src = get_log_msg_url(msg);
  351.         return ting;
  352.     };
  353.     */
  354.     
  355.     var track_click = function($a, msg)
  356.     {
  357.         $a.mouseup(function(event)
  358.         {
  359.             var original_href = $a.attr("href");
  360.             msg["redirect_to"] = original_href;
  361.             $a.attr("href", get_log_msg_url(msg));
  362.  
  363.             setTimeout(function()
  364.             {
  365.                 $a.attr("href", original_href);
  366.             }, 10);
  367.         });
  368.     };        
  369.     
  370.     
  371.     /*
  372.     var log_msg_blocking = function(msg)
  373.     {
  374.         try
  375.         {
  376.             var req = new XMLHttpRequest();
  377.             req.open("GET", get_log_msg_url(msg), false);   
  378.             req.send(null);  
  379.             return req;
  380.         }
  381.         catch(ex)
  382.         {
  383.         }
  384.     };
  385.     */
  386.  
  387.     var arrayDeepEq = function(a1, a2)
  388.     {
  389.         if(a1.length != a2.length)
  390.         {
  391.             return false;
  392.         }
  393.         for(var i = 0; i < a1.length; i++)
  394.         {
  395.             if(a1[i] != a2[i])
  396.             {
  397.                 return false
  398.             }
  399.         }
  400.         return true;
  401.     };
  402.  
  403.     var isDesignMode = function(doc)
  404.     {
  405.         return !(document.designMode == "off"
  406.                 || doc.designMode == "Off" || doc.designMode == "Inherit") // hack for IE
  407.     };
  408.     
  409.     var isLeftClick = function(event)
  410.     {
  411.         return (!$.browser.msie && event.button == 0) 
  412.             || ($.browser.msie && event.button == 1); // hack for IE
  413.     };
  414.  
  415.     var getSelection = function(doc)
  416.     {
  417.         try
  418.         {
  419.             return doc.defaultView.getSelection(); // correct way for Firefox
  420.         }
  421.         catch(err){}
  422.         try
  423.         {
  424.             return window.getSelection(); // hack for IE
  425.         }            
  426.         catch(err){}
  427.         try
  428.         {
  429.             return document.getSelection(); // hack for IE
  430.         }            
  431.         catch(err){}
  432.         try // hack for IE
  433.         {
  434.             var selection = document.selection && document.selection.createRange();
  435.             selection.toString = function() { return this.text };
  436.             return selection;
  437.         }            
  438.         catch(err){}
  439.         return null;
  440.     };
  441.  
  442.     var getLastRange = function(selection)
  443.     {
  444.         var lastRange = selection.getRangeAt(selection.rangeCount - 1);
  445.         for(var r = selection.rangeCount - 1; r >= 0; r--)
  446.         {
  447.             if(!selection.getRangeAt(r).collapsed) {
  448.                 lastRange = selection.getRangeAt(r);
  449.                 break;
  450.             }
  451.             else {
  452.                 //alert("invalid range found");
  453.             }
  454.         } //fix Firefox bug? with selecting backwards: it creates an range at the end that is collapsed
  455.         return lastRange;
  456.     };        
  457.     
  458.     var isValidSelection = function(selection)
  459.     {
  460.         try
  461.         {
  462.             /*
  463.             //alert(selection.toString() + ":" + 
  464.                 selection.anchorNode.nodeName + 
  465.                 ":" + selection.anchorOffset + ":" + 
  466.                 selection.focusNode.nodeName + ":" + selection.focusOffset + ":" + selection.isCollapsed);
  467.             //alert(selection.anchorNode == selection.focusNode);
  468.             */
  469.             if(selection.toString())
  470.             {
  471.                 if(selection.anchorNode.nodeName.toLowerCase() == "object")
  472.                 {//fix problems with flash players on myspace such as http://www.myspace.com/entershikari
  473.                     return false;
  474.                 }
  475.                 if(selection.anchorNode == selection.focusNode && 
  476.                     selection.toString().replace(/^\s+|\s+$/g,"").length > Math.abs(selection.focusOffset - selection.anchorOffset))
  477.                 {//fix <a> with title button on http://news.bbc.co.uk/2/hi/middle_east/8098776.stm
  478.                     return false;
  479.                 }
  480.                 /*
  481.                 if(!(selection.anchorNode.nodeName.toLowerCase() == "#text" && 
  482.                      selection.focusNode.nodeName.toLowerCase() == "#text"))
  483.                 {//too restrictive
  484.                     return false;
  485.                 }
  486.                 */
  487.                 var containsInput = false;
  488.                 $("textarea, input[type=text]", doc).each(function(i)
  489.                 {
  490.                     if(selection.containsNode(this, true))
  491.                     {
  492.                         containsInput = true; //contains input/textarea
  493.                         return false;//break
  494.                     }
  495.                 });
  496.                 return !containsInput;
  497.             }
  498.             else
  499.             {
  500.                 return false;
  501.             }
  502.         }
  503.         catch(err) //dirty hack for IE
  504.         {
  505.             return selection.toString();
  506.         }
  507.     };
  508.     
  509.     var show_popup_bubble = function(doc)
  510.     {
  511.         //"popup_bubble_loaded"
  512.         var getSelectionKey = function(selection)
  513.         {
  514.             try
  515.             {
  516.                 var lastRange = getLastRange(selection);//selection.getRangeAt(selection.rangeCount - 1);
  517.                 return [selection.toString(), lastRange.endContainer, lastRange.endOffset];
  518.             }
  519.             catch(err)
  520.             {   //alert("using hack"); //dirty IE hack
  521.                 return [selection.toString()];
  522.             }
  523.         };
  524.  
  525.         //BEGIN preview code
  526.         var homepageURL = "http://smarterfox.com/widget/";
  527.  
  528.         var getSearchResultsURL = function(url, terms)
  529.         {
  530.             var language = navigator.language ? navigator.language : navigator.userLanguage;
  531.             var url = url.replace(/{searchTerms}/g, encodeURIComponent(terms));
  532.             url = url.replace(/{language}/g, language);
  533.             return url;
  534.         };
  535.         var searchWikipediaURL = "http://smarterfox.com/wikisearch/search?q={searchTerms}&locale={language}";
  536.         var searchOneRiotURL = "http://www.oneriot.com/search?p=smarterfox&ssrc=" + config.source + "_popup_bubble&spid=8493c8f1-0b5b-4116-99fd-f0bcb0a3b602&q={searchTerms}";
  537.         var searchYandexURL = "http://yandex.ru/yandsearch?text={searchTerms}&clid=127504";
  538.         var searchDeliciousURL = "http://delicious.com/search?p={searchTerms}";
  539.         var searchTwitterURL = "http://search.twitter.com/search?q={searchTerms}";
  540.         var searchSurfCanyonURL = "http://search.surfcanyon.com/search?f=nrl1&q={searchTerms}&partner=fastestfox";
  541.         var tweetThisURL = "http://twitter.com/home?status={searchTerms}";
  542.         var searchBingURL = "http://www.bing.com/search?q={searchTerms}";
  543.         var searchBaiduURL = "http://www.baidu.com/s?wd={searchTerms}";
  544.         var searchRedditURL = "http://www.reddit.com/search?q={searchTerms}";
  545.         var searchYouTubeURL = "http://www.youtube.com/results?search_query={searchTerms}";
  546.         var searchWiktionaryURL = "http://en.wiktionary.org/wiki/Special:Search?search={searchTerms}&go=Define";
  547.         var searchGoogleURL = "http://www.google.com/search?q={searchTerms}";
  548.  
  549.         var buildPopupSearchBubbleLite = function(config, searchQuery)//, insertCallback) //dirty hack for IE
  550.         {
  551.             var $popupBubble = $('<a class="smarterwiki-popup-bubble smarterwiki-popup-bubble-lite smarterwiki-popup-bubble-active" href="' 
  552.                 + getSearchResultsURL(searchWikipediaURL, searchQuery) + '"></a>', doc);
  553.             if(config.openNewTab)
  554.             {
  555.                 $popupBubble.attr("target", "_blank");
  556.             }
  557.             //insertCallback($popupBubble);
  558.             return $popupBubble;     
  559.         };
  560.  
  561.         var buildPopupSearchBubbleFull = function(config, searchQuery)//, insertCallback)
  562.         {
  563.             var $popupBubble = $(
  564.                 '<span class="smarterwiki-popup-bubble smarterwiki-popup-bubble-active"></span>',
  565.                 doc
  566.             );
  567.             
  568.             var $popupBubbleLinks = $(
  569.                 '<span class="smarterwiki-popup-bubble-links smarterwiki-clearfix"></span>',
  570.                 doc).appendTo(
  571.                     $('<span class="smarterwiki-popup-bubble-body"></span>', doc)
  572.                         .appendTo($popupBubble)
  573.                 );
  574.  
  575.             var homepageLink = function(classes)
  576.             {
  577.                 var $a = $('<a href="' + homepageURL + '" class="' + classes + '"></a>', doc);
  578.                 if(config.openNewTab)
  579.                 {
  580.                     $a.attr("target", "_blank");
  581.                 }
  582.                 track_click($a, {name: "homepage_visited", source: config.source});
  583.                 return $a;
  584.             };
  585.             
  586.             var $popupBubbleTip = (
  587.                     //config.showHomepageLink ? homepageLink("smarterwiki-popup-bubble-tip") :
  588.                         $('<span class="smarterwiki-popup-bubble-tip"></span>', doc)
  589.                 ).appendTo($popupBubble);
  590.                 
  591.             var bubbleLinkAs = [];
  592.  
  593.             var addBubbleLink = function(title, icon_src, href, track)
  594.             {
  595.                 var $a = $('<a class="smarterwiki-popup-bubble-link"></a>', doc)
  596.                         .attr("href", href)
  597.                         //.attr("href", "#")
  598.                         .attr("title", title)
  599.                         .append(
  600.                             $('<img alt="" class="smarterwiki-popup-bubble-link-favicon" />', doc)
  601.                             .attr("src", icon_src)
  602.                         );
  603.  
  604.                 if(config.openNewTab)
  605.                 {
  606.                     $a.attr("target", "_blank");
  607.                 }
  608.                 
  609.                 if(track)
  610.                 {
  611.                     track_click($a, {name: "popup_bubble_searched", search_engine_title: title, source: config.source});
  612.                 }
  613.  
  614.                 bubbleLinkAs.push($a);
  615.                 return $a;
  616.             };
  617.  
  618.             //addBubbleLink("http://static.smarterfox.com/media/wiki-favicon.png", searchWikipediaURL(searchQuery), "Search Wikipedia");
  619.             if(config.searchWikipedia)
  620.             {
  621.                 addBubbleLink(
  622.                     "Search Wikipedia",
  623.                     //"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAIpwAACKcBMsYCAwAAAAd0SU1FB9kFEwgQLXKnj9oAAAPsSURBVDiNdVRZSGRXEH1Joz8icSIMJsEQEvKvov4ICoOYIAp+KKISkLiAgij5UGOMjgoug6CiKC64i/sSpVHcl7jv7W6722pcWmyNoqBW6hRpyYSZC8W7975bdU+dOrcUIlL+axYWFq+SkpLybWxsYo17VlZWX/H6DebOzs4/ent7/+Lu7v7z/31h7y8U5fvV1VWNra3tIObGvZqamtaHh4fHxMTExb29vcejoyMKCwt7jIqKWuD/bz4Y0MXF5e319bU2JyfngA99x/YJ22empqZuERERKwcHB9Td3U37+/u0srJCc3NzNDIyQk1NTVcqleonPvv6JSCPL87OznQ8p+TkZC2vv2GzcnNz+83a2joqLy9vCQFnZ2dpfX2dlpaWqLe3lzo7O+WStLS0ORMTE7+XgCkpKTX07/Dz86PIyEhDVlaWISMjgxISEmRfp9PRzs4O7e7uEtMi6EZHRyVweHg4gp6bm5tbKK958PlbODES+ZmZmQmkxjsE2d3dHWm1WsrOzqa6ujoaGhqigYEBGh4epvT0dCovLyd7e3sfhR3fGR0vLy9fULa0tMj8/PycNBoNcVGIi0NxcXHU09NDY2Nj1N/fL2mXlZXJJV5eXkXK9va2DojggIDPz8/iuLGxQcvLy8IXEN7c3JBer5f14uKiIOzr66P29naqqqqiiooK8vf3n1aYbP3ExIQcZkkIKgcHBwJ/BoNB1ltbW8IbF466urrk3OTkpFhDQ4MEZA7Jx8fnSGEJ6I2pHh4eyvf2ViglVBbBwBMQb25u0sLCgnAXExMjVLS1tVFJSYmkHRoa+pfCmydwPjk5EYf7+3txwBoVRTFmZmZetFdcXEyBgYGUm5srVa6traWioiIqKCig4ODgVYVJnUE6LGpBhLQQDMjAHeaQzPT0tASG7iorK0U2kAwC4hIE9PT0HFZYvB7j4+NPQHlxcSGFOD4+Fvnw8xKOUGnwxAWkqakpqSz7CJ/V1dXEmiV+/+To6Pi7CJvFq356ehIHaA2ogPjq6krSRlVbW1ulqoODgyIbyMfX15dKS0spNjYWAf+2tLT8UgLyJAIPHinPz89LFcEXJIJUcdHa2ppIBAjVajWlpqYSNwcqLCwUdEFBQX9+ysP4llXcSf7gFO6A8PT0lJqbm4UXvB6kBc6QKgz/sAfu8Ers7OzecYxv3+s2PD53dXX9FVUFCiCqr6+njo4OSRMBwSN3FylKfn4+MQgKCAhAC1N9rB+aODk5vWUU5+ARUoHu8CpQ0cbGRjFcxA3kkjtRAft8/dEGazRuRabcZH8ICQkpjo6OVjNHmvj4+GXuiyMeHh453ATCzMzMXn3I9x8oCiuuorpqawAAAABJRU5ErkJggg==",
  624.                     "http://static.smarterfox.com/media/wiki-favicon-sharpened.png", 
  625.                     getSearchResultsURL(searchWikipediaURL, searchQuery),
  626.                     true
  627.                 );
  628.             }
  629.             
  630.             for(var s = 0; s < config.customSearchEngines.length; s++)
  631.             {
  632.                 addBubbleLink(
  633.                         config.customSearchEngines[s][0], 
  634.                         config.customSearchEngines[s][1],
  635.                         getSearchResultsURL(config.customSearchEngines[s][2], searchQuery),
  636.                         true                        
  637.                 );
  638.             }
  639.  
  640.             if(config.searchOneRiot)
  641.             {
  642.                 addBubbleLink(
  643.                     "Search OneRiot",
  644.                     //"data:;base64,AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAA////APbu/A++dfOOjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/++dfOO9u78D////wD///8AqUfvv40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+wVvCu////ANOh9mCNCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6//TofZgmyjt3o0K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/5so7d6NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/7FX8f/jwvr/48L6/+PC+v/jwvr/48L6/+PC+v/jwvr/zZT2/40K6/+NCuv/48L6/+PC+v+4ZvP/jQrr/82U9v/jwvr/zZT2/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+4ZvP/////////////////////////////////////////////////jQrr/40K6////////////+PC+v+NCuv/1KP4////////////jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/ojjv//jw/v////////////////////////////////////////////////+UGez/jQrr/+PC+v//////48L6/40K6//GhfX///////////+bKe7/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/6I47//48P7//////////////////////////////////////////////////////6pH8P+NCuv/48L6////////////jQrr/7hm8////////////6pH8P+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+UGez/+PD+////////////////////////////////////////////////////////////qkfw/40K6//GhfX///////////+NCuv/qkfw////////////sVfx/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/lBns/+rR+//////////////////////////////////////////////////////////////////GhfX/jQrr/8aF9f///////////6I47/+iOO/////////////GhfX/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6//Uo/j//////////////////////////////////////////////////////////////////////8aF9f+NCuv/sVfx////////////qkfw/40K6////////////82U9v+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/6pH8P/48P7/////////////////////////////////////////////////////////////////48L6/40K6/+qR/D///////////+/dfT/jQrr//jw/v//////48L6/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/6I47//48P7////////////////////////////////////////////////////////////GhfX/jQrr/7FX8f///////////6pH8P+UGez////////////NlPb/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/6I47//q0fv/////////////////////////////////////////////////6tH7/5QZ7P+iOO//+PD+///////NlPb/lBns/+rR+///////6tH7/5QZ7P+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/5QZ7P/q0fv//////////////////////////////////////+rR+/+UGez/lBns//jw/v//////1KP4/40K6//Uo/j//////+rR+/+UGez/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/5QZ7P/jwvr////////////////////////////48P7/lBns/5QZ7P/q0fv//////9uy+f+NCuv/1KP4///////48P7/mynu/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6//Uo/j/////////////////+PD+/6I47/+UGez/6tH7///////q0fv/lBns/7919P//////+PD+/6I47/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6//NlPb///////////+iOO//jQrr/7919P//////6tH7/5QZ7P+bKe7///////////+qR/D/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+xV/H/sVfx/40K6/+NCuv/jQrr/7919P+bKe7/jQrr/40K6/+xV/H/sVfx/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/ojjuz40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/6I47s/asfhQjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/2rH4UP///wC3ZvKfjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/7dm8p////8A////AP///wDFg/SBjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6//Fg/SB////AP///wD///8A////AP///wDv3/sfzJL1cMWD9IHFg/SBxYP0gcWD9IHFg/SBxYP0gcWD9IHFg/SBxYP0gcWD9IHFg/SBxYP0gcWD9IHFg/SBxYP0gcWD9IHFg/SBxYP0gcWD9IHFg/SBxYP0gcWD9IHTofZg9u78D////wD///8A////AMAAAAOAAAABgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAcAAAAP4AAAfKAAAABAAAAAgAAAAAQAgAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAObM+jKZJO3jjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/mSTt4+jP+i+hNu7PjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+hNu7PjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/vXHz//Hg/P/x4Pz/8eD8/+vV+/+NCuv/8eD8/61P8P/gvvn/uWny/40K6/+NCuv/jQrr/40K6/+NCuv/slrx//37/v//////////////////////lh3s//Hg/P+/dfP/37r5/9Cb9/+NCuv/jQrr/40K6/+NCuv/p0Pv//37/v///////////////////////////6I47v/iwvr/y5D2/9Kf9//dtvn/jQrr/40K6/+NCuv/jQrr/922+f////////////////////////////////+wVvH/1qf3/9mu+P/EgPT/69X7/40K6/+NCuv/jQrr/40K6/+SFez/4L75///////////////////////58/7/ojju/+nR+//CfPT/37r5/9Kf9/+NCuv/jQrr/40K6/+NCuv/jQrr/44N6//Yqvj////////////9+/7/qUfv/922+f/Ol/b/zZP2/9+6+f+ODev/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/8uQ9v//////slrx/8+X9v/Zrvj/u23z/+jN+/+SFez/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/nzDu/40K6/+ZJO3/kBHr/5Yd7P+WHez/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+SFevzjQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+SFevzxob0e40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/jQrr/40K6/+NCuv/xob0e////wDPmvZnqknvu6hF78CoRe/AqEXvwKhF78CoRe/AqEXvwKhF78CoRe/AqEXvwKhF78CsTfC20Z32ZP///wCAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAADAAwAA",
  645.                     //"http://www.oneriot.com/images/favicon.ico", 
  646.                     "http://static.smarterfox.com/media/popup_bubble/oneriot-favicon.ico",
  647.                     getSearchResultsURL(searchOneRiotURL, searchQuery),
  648.                     true                    
  649.                 );
  650.             }
  651.             if(config.searchDelicious)
  652.             {
  653.                 addBubbleLink(
  654.                     "Search Delicious",
  655.                     "http://delicious.com/favicon.ico", 
  656.                     getSearchResultsURL(searchDeliciousURL, searchQuery),
  657.                     true
  658.                 );
  659.             }
  660.             if(config.searchSurfCanyon)
  661.             {
  662.                 addBubbleLink(
  663.                     "Search Surf Canyon",
  664.                     "http://surfcanyon.com/favicon.ico", 
  665.                     getSearchResultsURL(searchSurfCanyonURL, searchQuery),
  666.                     true
  667.                 );
  668.             }            
  669.             if(config.searchTwitter)
  670.             {
  671.                 addBubbleLink(
  672.                     "Search Twitter",
  673.                     //"data:;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAADw4ikA7d0HAO3cAAD16nwA8+doAP7+/QDz52cA/PrpAPTpdgD9/f0A///+AP39/gD8/PkA7d0IAPv42QD9/fwA/P3/APv2yADs2gAA+/v4APv2xwD264QA8OI5APPnZgDu3QAA+PGgAPXqgADx5E4A9+6aAO/gGAD164UA9ep+APDiOAD+/foA+fr6APfulADx5VAA7dsAAPz89QD37pMA9up8APz8/AD8+dcA/PjUAPz3zQD79MIA+/r4AP7++AD8/PsA/frnAPr1vgD7+eEA9uyLAP7+/AD9+/AA9eyFAPz54QD7+/YA7+EjAPr31QD48KUA9ep3APz53gD16n8A/Pv5APjxpgD48akA+/vxAPr7+gDz6GgA798AAP388gDx5EYA9Ol1APXqdQDu3hkA8uZYAPPnXgD+/v8A/PvzAP7//gDv4AAA/v//APz79AD48bEA+fO0APbsjAD7+NwA/fvtAPbtkADv4BQA+/jfAPv42gD79soA8+dgAPPmYwD9/PoA/f37APz8+AD9/PkA+fS8APDjOgD8/PcA+/fYAPbuigD69sYA+PGiAPv65gD37pYA/PrxAOzbAAD69s8A/PrqAPbthgD16XYA9elxAPv69QD8+uIA+/jYAPv54wD69tQA7NwAAPjxpAD48Z4A7t4AAP7+/gD///8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAgAUibVx2Dg52TwyAgICAgA8JIzoBAQ0NAiBHgICAgAVjTRIYfHx8fHwSMoCAgIAQcW58fAICAnklSzGAgIB9QwBGUVpoQWoZej6AgICAfXg6AB17EAkLCylQgICAgFJvZUgWaTAKfX01gICAgIBOOyRMG2Q2B3AHayGAgICAfWdeBEUEBgQGBl83L4CAgIBXcz0ICElKcgg9FyqAgICAWz8VHh8DAygDAxpYgICAfTM0WVZVXREUFBF1YICAgH13bBwnPkQTEy5AD4CAgIB9B0JUPDgMgICAgICAgICACmYrLSwmBYCAgICAgICAgIBhdFM5YoCAgICAgICAgPADAADgAwAAwAMAAMADAACABwAAgAcAAIAPAACABwAAgAMAAMADAADAAwAAgAMAAIAHAACA/wAAgP8AAMH/AAA=",
  674.                     "http://twitter.com/favicon.ico", 
  675.                     getSearchResultsURL(searchTwitterURL, searchQuery),
  676.                     true
  677.                 );
  678.             }
  679.             if(config.tweetThis)
  680.             {
  681.                 addBubbleLink(
  682.                     "Tweet This!",
  683.                     "http://static.smarterfox.com/media/finderfox/tweet_this.png", 
  684.                     getSearchResultsURL(tweetThisURL, '"' + searchQuery + '" - ' + doc.location.href),
  685.                     true                    
  686.                 );
  687.             }
  688.             if(config.searchBing)
  689.             {
  690.                 addBubbleLink(
  691.                     "Search Bing",
  692.                     "http://www.bing.com/favicon.ico", 
  693.                     getSearchResultsURL(searchBingURL, searchQuery),
  694.                     true                    
  695.                 );
  696.             }
  697.             if(config.searchBaidu)
  698.             {
  699.                 addBubbleLink(
  700.                     "Search Baidu",
  701.                     "http://www.baidu.com/favicon.ico", 
  702.                     getSearchResultsURL(searchBaiduURL, searchQuery),
  703.                     true                    
  704.                 );
  705.             }
  706.             if(config.searchReddit)
  707.             {
  708.                 addBubbleLink(
  709.                     "Search Reddit",
  710.                     "http://www.reddit.com/favicon.ico", 
  711.                     getSearchResultsURL(searchRedditURL, searchQuery),
  712.                     true                    
  713.                 );
  714.             }
  715.             if(config.searchYouTube)
  716.             {
  717.                 addBubbleLink(
  718.                     "Search YouTube",
  719.                     "http://www.youtube.com/favicon.ico", 
  720.                     getSearchResultsURL(searchYouTubeURL, searchQuery),
  721.                     true                    
  722.                 );
  723.             }            
  724.             if(config.searchWiktionary)
  725.             {
  726.                 addBubbleLink(
  727.                     "Search Wiktionary",
  728.                     "http://en.wiktionary.org/favicon.ico", 
  729.                     getSearchResultsURL(searchWiktionaryURL, searchQuery),
  730.                     true                    
  731.                 );
  732.             }
  733.             if(config.searchGoogle)
  734.             {
  735.                 addBubbleLink(
  736.                     "Search Google",
  737.                     //"data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7PT7/3zF6/9Ptu//RbHx/0227/+Tzvb/9vv5/97h0f9JeBz/NHoA/z98Av9AfAD/PHsA/0F6AP8AAAAA/vz7/1+33/8Mp+z/FrHw/xWy8f8bs/T/Hqrx/3zE7v////7/t8qp/zF2A/87gwH/P4ID/z59AP8+egD/Q3kA/97s8v8botj/ELn3/wy58f8PtfL/D7Lw/xuz9P8vq+f/8/n///779v9KhR3/OYYA/0GFAv88hgD/QIAC/z17AP/0+/j/N6bM/wC07/8Cxf7/CsP7/wm+9v8Aqur/SrDb//7+/v///P7/VZEl/zSJAP87jQD/PYYA/0OBBf8+fQH///3//9Dp8/84sM7/CrDf/wC14/8CruL/KqnW/9ns8f/8/v//4OjX/z+GDf85kAD/PIwD/z2JAv8+hQD/PoEA/9C7pv/97uv////+/9Xw+v+w3ej/ls/e/+rz9///////+/z6/22mSf8qjQH/OJMA/zuQAP85iwL/PIgA/zyFAP+OSSL/nV44/7J+Vv/AkG7/7trP//7//f/9//7/6/Lr/2uoRv8tjQH/PJYA/zuTAP87kwD/PY8A/z2KAP89hAD/olkn/6RVHP+eSgj/mEgR//Ho3//+/v7/5Ozh/1GaJv8tlAD/OZcC/zuXAv84lAD/O5IC/z2PAf89iwL/OIkA/6hWFf+cTxD/pm9C/76ihP/8/v//+////8nav/8fdwL/NZsA/zeZAP83mgD/PJQB/zyUAf84jwD/PYsB/z6HAf+fXif/1r6s//79///58u//3r+g/+3i2v/+//3/mbiF/yyCAP87mgP/OpgD/zeWAP85lgD/OpEB/z+TAP9ChwH/7eHb/////v/28ej/tWwo/7tUAP+5XQ7/5M+5/////v+bsZn/IHAd/zeVAP89lgP/O5MA/zaJCf8tZTr/DyuK//3////9////0qmC/7lTAP/KZAT/vVgC/8iQWf/+//3///j//ygpx/8GGcL/ESax/xEgtv8FEMz/AALh/wAB1f///f7///z//758O//GXQL/yGYC/8RaAv/Ojlf/+/////////9QU93/BAD0/wAB//8DAP3/AAHz/wAA5f8DAtr///////v7+/+2bCT/yGMA/89mAP/BWQD/0q+D///+/////P7/Rkbg/wEA+f8AA/z/AQH5/wMA8P8AAev/AADf///7/P////7/uINQ/7lXAP/MYwL/vGIO//Lm3P/8/v//1dT2/woM5/8AAP3/AwH+/wAB/f8AAfb/BADs/wAC4P8AAAAA//z7/+LbzP+mXyD/oUwE/9Gshv/8//3/7/H5/zo/w/8AAdX/AgL6/wAA/f8CAP3/AAH2/wAA7v8AAAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAA==",
  738.                     "http://www.google.com/favicon.ico", 
  739.                     getSearchResultsURL(searchGoogleURL, searchQuery),
  740.                     false                    
  741.                 );
  742.             }
  743.             if(config.searchYandex)
  744.             {
  745.                 addBubbleLink(
  746.                     "Search Yandex",
  747.                     "http://www.yandex.ru/favicon.ico",
  748.                     getSearchResultsURL(searchYandexURL, searchQuery),
  749.                     true                    
  750.                 );
  751.             }
  752.             
  753.             if(config.showHomepageLink)
  754.             {
  755.                 var $a = addBubbleLink(
  756.                     "What is this?",
  757.                     "http://static.smarterfox.com/media/img/smarterfox-logo.png",
  758.                     homepageURL
  759.                 );
  760.                 track_click($a, {name: "homepage_visited", source: config.source});
  761.             }
  762.  
  763.  
  764.             var numRows = config.forceSingleRow ? 1 : Math.floor(Math.sqrt(bubbleLinkAs.length));
  765.             var numCols = Math.ceil(bubbleLinkAs.length / numRows);
  766.             bubbleLinkAs.reverse();
  767.             var a_bubbleLinkA = bubbleLinkAs[0];
  768.             while(bubbleLinkAs.length)
  769.             {
  770.                 var $row = $('<span class="smarterwiki-popup-bubble-links-row smarterwiki-clearfix"></span>', doc).prependTo($popupBubbleLinks);
  771.                 for(var c = 0; c < numCols; c++)
  772.                 {
  773.                     if(bubbleLinkAs.length)
  774.                     {
  775.                         $row.append(bubbleLinkAs.pop());
  776.                     }
  777.                     else
  778.                     {
  779.                         break;
  780.                     }
  781.                 }
  782.             }
  783.             
  784.             $popupBubble.css("margin-left", "-" + (3*2 + 3*2 + numCols*18 + (numCols-1)*3) + "px");
  785.             $popupBubble.css("margin-top", "-" + (3*2 + 3*2 + numRows*18 + (numRows-1)*3 + 6) + "px");
  786.  
  787.             //insertCallback($popupBubble);
  788.             
  789.             //$popupBubble.css("margin-left", "-" + $popupBubble.width() + "px");
  790.             //$popupBubble.css("margin-top", "-" + $popupBubble.height() + "px");
  791.  
  792.             return $popupBubble;
  793.         };
  794.         //END preview code
  795.         
  796.         var buildPopupSearchBubble = function(searchQuery)//, insertCallback)
  797.         {
  798.             if(!$.browser.msie || ($.browser.msie && $.browser.version.indexOf("8")==0))
  799.             {
  800.                 return buildPopupSearchBubbleFull(config, searchQuery);//, insertCallback);
  801.             }
  802.             else
  803.             {//dirty hack for IE
  804.                 return buildPopupSearchBubbleLite(config, searchQuery);//, insertCallback); //dirty hack for IE
  805.             }
  806.         };
  807.         
  808.         var insertPopupBubble = function($popupBubble, selection)
  809.         {
  810.             //alert($(".smarterwiki-popup-bubble-active").length);
  811.             //////////////////log_msg_async({name: "popup_bubble_inserted", source: config.source});
  812.             try
  813.             {
  814.                 var lastRange = getLastRange(selection);
  815.                 //$("<div></div>").append(lastRange.cloneContents())[0].innerHTML
  816.                 var newRange = doc.createRange();
  817.                 newRange.setStart(lastRange.endContainer, lastRange.endOffset);
  818.                 newRange.insertNode($popupBubble[0]);
  819.                 return $popupBubble;
  820.             }
  821.             catch(err) //dirty hack for IE
  822.             {
  823.                 var $tmp = $('<div></div>', doc).append($popupBubble);
  824.                 var newRange = selection.duplicate();
  825.                 newRange.setEndPoint("StartToEnd", selection);
  826.                 newRange.pasteHTML($tmp[0].innerHTML);
  827.                 return $(".smarterwiki-popup-bubble-active");
  828.             }
  829.         };
  830.         
  831.         var cleanupPopupBubble = function($popupBubble)
  832.         {
  833.             if(!isValidSelection(getSelection(doc)) || 
  834.                 !arrayDeepEq($popupBubble.data("selectionKey"), getSelectionKey(getSelection(doc)))
  835.             ) //is this still a valid popup?
  836.             {
  837.                 $popupBubble.removeClass("smarterwiki-popup-bubble-active");
  838.                 //alert("removing");
  839.                 if(config.animate)
  840.                 {
  841.                     $popupBubble.stop(true).fadeTo("normal", 0, function() //no longer valid, remove
  842.                     {
  843.                         $popupBubble.remove();
  844.                     });
  845.                 }
  846.                 else
  847.                 {
  848.                     $popupBubble.remove();
  849.                 }                
  850.             }
  851.         };
  852.  
  853.  
  854.         $(doc).mousedown(function(event)
  855.         {
  856.             //if(isLeftClick(event))
  857.             $(".smarterwiki-popup-bubble", doc).each(function(i)
  858.             {
  859.                 cleanupPopupBubble($(this));
  860.             });
  861.         });
  862.  
  863.         $(doc).mouseup(function(event)
  864.         {
  865.             $(".smarterwiki-popup-bubble", doc).each(function(i)
  866.             {
  867.                 cleanupPopupBubble($(this));
  868.             });
  869.             
  870.             get_config(function(conf)
  871.             {
  872.                 config = conf;
  873.                 if(isLeftClick(event))
  874.                 {
  875.                     if(!isDesignMode(doc)) //this can be set after $.ready() :(
  876.                     {
  877.                         var selection = getSelection(doc);
  878.                         if(config.showPopupBubble && isValidSelection(selection))
  879.                         {
  880.                             var shouldInsert = $(".smarterwiki-popup-bubble-active").length == 0;
  881.                             if(shouldInsert)
  882.                             {
  883.                                 var $popupBubble = buildPopupSearchBubble(selection.toString());//, function($popupBubble)
  884.                                 $popupBubble = insertPopupBubble($popupBubble, selection);
  885.                                 //alert("inserted");
  886.                                 $popupBubble.data("selectionKey", getSelectionKey(selection), null);
  887.                                 if(config.animate)
  888.                                 {
  889.                                     $popupBubble.css("opacity", 0.0);
  890.                                     if(config.enableGhosting)
  891.                                     {
  892.                                         var ghosted_opacity = 0.25;
  893.                                         $popupBubble.animate({opacity: 1.}, 200)
  894.                                                     .animate({opacity: 1.}, 1300)//.fadeTo("fast", ghosted_opacity)
  895.                                                     .animate({opacity: ghosted_opacity}, 700)//, zIndex: -100000
  896.                                                     .hover(function()//need this because the :hover css doesn't work in quirks mode
  897.                                         {
  898.                                             $popupBubble.stop(true).css("opacity", 1.0);//.css("z-index", 2147483647);
  899.                                         }, function()
  900.                                         {
  901.                                             $popupBubble.stop(true).animate({opacity: ghosted_opacity}, 200);
  902.                                             //.css("opacity", ghosted_opacity).css("z-index", 2147483647);
  903.                                         });                                    
  904.                                     }
  905.                                     else
  906.                                     {
  907.                                         $popupBubble.fadeTo("fast", 1.0);                                    
  908.                                     }
  909.                                 }
  910.                             }
  911.                         }
  912.                     }
  913.                     else
  914.                     {
  915.                         // in rich editor
  916.                     }                    
  917.                 }
  918.             });
  919.         });
  920.     };
  921.  
  922.     var doc = document;
  923.     var blacklist_urlRegExp = new RegExp("https?://(([^/]*\.)?nytimes.com.*)");
  924.     var blacklist_match = blacklist_urlRegExp.exec(doc.location.href);
  925.     if(blacklist_match == null) //ok, add popup bubble
  926.     {
  927.         $(doc).ready(function()
  928.         {
  929.             if(!isDesignMode(doc))
  930.             {
  931.                 show_popup_bubble(doc);
  932.             }
  933.             else
  934.             {
  935.                 // in rich editor
  936.             }
  937.         });
  938.     }
  939.     else
  940.     {
  941.         // disabled on this page b/c of blacklist
  942.     }
  943. }());